library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.Achtung_const.all;

entity Achtung_TOP is
	port (
		--in_RST		: in std_logic;
		CLOCK_50		: in std_logic;
		CLOCK_27		: in std_logic;
		--temp_r,temp_g,temp_b	: in std_logic;
		KEY			: in std_logic_vector(3 downto 0);
		SW			: in std_logic_vector(17 downto 0);
		LEDR		: out std_logic_vector(17 downto 0);
		--VGA ports
		VGA_R		: out std_logic_vector(9 downto 0);
		VGA_G		: out std_logic_vector(9 downto 0);
		VGA_B		: out std_logic_vector(9 downto 0);
		VGA_HS		: out std_logic;
		VGA_VS		: out std_logic;
		VGA_SYNC	: out std_logic;
		VGA_BLANK	: out std_logic;
		VGA_CLK		: out std_logic;
--		--PAD 1 ports
		PAD1_CLK	: out std_logic;
		PAD1_STROBE : out std_logic;
		PAD1_INPUT	: in std_logic;
		--PAD 2 ports
		PAD2_CLK	: out std_logic;
		PAD2_STROBE : out std_logic;
		PAD2_INPUT	: in std_logic;
		
		--SRAM
		SRAM_DQ	: inout SRAM_Data;
		SRAM_ADDR	: out SRAM_Address;
		SRAM_WE_N	: out std_logic;
		SRAM_CE_N	: out std_logic;
		SRAM_OE_N	: out std_logic;
		SRAM_UB_N	: out std_logic;
		SRAM_LB_N	: out std_logic
	);
end entity;

architecture arch_top of Achtung_TOP is
	component Clock_Divider is
	port(	
	inCLK	: in std_logic;
	outCLK	: out std_logic
	);
	end component;
	
	component VGA_Synchro is
	port
	(	clock_25Mhz, red, green, blue		: IN	STD_LOGIC;
		red_out, green_out, blue_out, horiz_sync_out, vert_sync_out, blank, video_off	: OUT	STD_LOGIC;
		pixel_row, pixel_column: OUT unsigned(9 DOWNTO 0)
	);
	end component;
	
	component controller is 
	port (
		clk_in :in std_logic;
		clk_out :out std_logic;
		
		strobe: out std_logic;
	
		PAD_INPUT : in std_logic;
		
		A: out std_logic;
		b: out std_logic;
		sele: out std_logic;
		start: out std_logic;
		u: out std_logic;
		d: out std_logic;
		l: out std_logic;
		r: out std_logic
		);
	end component;
	
	component Game_Machine is
	port(
	clk						: in std_logic;
	clk_25					: in std_logic;
	reset					: in std_logic;
	start_P1				: in std_logic;
	start_P2				: in std_logic;
	init_x_P1, init_x_P2	: out unsigned(9 downto 0);
	init_y_P1, init_y_P2	: out unsigned(9 downto 0);
	init					: out std_logic;
	r,g,b					: out std_logic;
	videoOff				: in std_logic;
	R_SRAM, G_SRAM, B_SRAM	: in std_logic;
	X_VGA, Y_VGA			: in unsigned(9 downto 0);
	X_SRAM, Y_SRAM			: out unsigned(9 downto 0);
	SRAM_COMMAND			: out std_logic_vector(1 downto 0);
	completed				: in std_logic;
	P1_next_x, P1_next_y	: in unsigned(9 downto 0);
	out_pix					: out RAM_Data
	);
end component;
	
component DecIncCounter is 
	port (
	clk							: in std_logic;
	dec, inc					: in std_logic;
	count						: out unsigned(2 downto 0)
	);
end component;	

component Snake_Movement_Controller is 
	port (
	trigger, init			: in std_logic;
	angle					: in unsigned(2 downto 0);
	next_x					: out unsigned(9 downto 0);
	next_y					: out unsigned(9 downto 0);
	init_x					: in unsigned(9 downto 0);
	init_y					: in unsigned(9 downto 0)
	);
end component;



component SRAM_driver is
	port 
	(
		clk		: in std_logic;
		rst		: in std_logic;
		
		SRAM_D	: inout SRAM_Data;
		SRAM_A	: out SRAM_Address;
		SRAM_WE	: out std_logic;
		SRAM_CE	: out std_logic;
		SRAM_OE	: out std_logic;
		SRAM_UB	: out std_logic;
		SRAM_LB	: out std_logic;
	
	
		row 		:in unsigned(9 downto 0);
		column 		:in unsigned(9 downto 0);
	
		pixel_in 	: in std_logic_vector(1 downto 0);
		pixel_out 	: out std_logic_vector(1 downto 0);
	
	
		command		: in std_logic_vector(1 downto 0);
		done		: out std_logic
	);

end component;

component RAM_Data_To_Colors is 
	port (
	code						: in RAM_Data;
	r,g,b						: out std_logic
	);
end component;

	--internal signals declaration
	signal clk_25,r,g,b 			: std_logic;
	signal pad1_start, pad2_start	: std_logic;
	signal pad1_left, pad2_left		: std_logic;
	signal pad1_right,pad2_right	: std_logic;
	signal VIDEO_OFF,INIT			: std_logic;
	signal INIT_X_1, INIT_Y_1		: unsigned(9 downto 0);
	signal vga_x, vga_y				: unsigned(9 downto 0);
	signal r_ram,g_ram,b_ram		: std_logic;
	signal code_from_ram			: RAM_Data;
	signal ramX, ramY				: unsigned (9 downto 0);
	signal addrComm,combinedComm	: std_logic_vector (1 downto 0);
	signal DataToAddress,DataToController	: SRAM_Data;
	signal oper_done				: std_logic;
	signal converted_address		: SRAM_Address;
	signal byte_sig, done_syg		: std_logic;
	signal p1_n_x, p1_n_y			: unsigned (9 downto 0);
	signal pixel_to_write			: RAM_Data;
	signal P1_angle					: unsigned(2 downto 0);
	signal baba : std_logic;
	
	begin
	
	VGA_CLK <= clk_25;
	VGA_SYNC <= '0';
	LEDR(17) <= INIT;
	LEDR(16) <= SW(16);
	LEDR(15) <= SW(15);
	LEDR(0)	 <= pad1_left;
	LEDR(1)  <= pad1_right;
	LEDR(2)  <= pad1_start;
	
	
	process(VIDEO_OFF)
	begin
		if(VIDEO_OFF = '1') then
		
			LEDR(5) <= '1';
			LEDR(7) <= '0';
			
		else
		
			LEDR(5) <= '0';
			LEDR(7) <= '1';
		
		end if;
	end process;
	
	P1_Angle_Counter : DecIncCounter
	port map(
	clk							=> VIDEO_OFF,
	dec							=> pad1_right,
	inc							=> pad1_left,
	count						=> P1_angle	
	);
	
	SRAM_Controller : SRAM_driver

	port map(
		clk		=> CLOCK_50,
		rst		=> baba,
		
		SRAM_D	=> SRAM_DQ,
		SRAM_A	=> SRAM_ADDR,
		SRAM_WE	=> SRAM_WE_N,
		SRAM_CE	=> SRAM_CE_N,
		SRAM_OE	=> SRAM_OE_N,
		SRAM_UB	=> SRAM_UB_N,
		SRAM_LB	=> SRAM_LB_N,
	
	
			row 		=> ramY,
		column 		=> ramX,
	
	
			pixel_in 	=> pixel_to_write,
		pixel_out 	=> code_from_ram,
	
	
		command		=> combinedComm,
		done		=> oper_done
		
	);
	
	Color_Converter : RAM_Data_To_Colors
	port map(
	code			=> code_from_ram,
	r				=> r_ram,
	g				=> g_ram,
	b				=> b_ram
	);
		
	myClock25	: Clock_Divider
	port map(
	inCLK	=>	CLOCK_50,
	outCLK	=>	clk_25
	);
	
	Controller_P1 : controller	
	port map(
		clk_in 		=> CLOCK_27,
		clk_out		=> PAD1_CLK,
		
		strobe		=> PAD1_STROBE,
	
		PAD_INPUT 	=> PAD1_INPUT,
		b			=> baba,
		u			=> pad1_start,
		l			=> pad1_left,
		r			=> pad1_right
	);
	
	Controller_P2 : controller	
	port map(
		clk_in 		=> CLOCK_27,
		clk_out		=> PAD2_CLK,
		
		strobe		=> PAD2_STROBE,
	
		PAD_INPUT 	=> PAD2_INPUT,
		
		A			=> pad2_start,
		l			=> pad2_left,
		r			=> pad2_right
	);
	
	VGA_Output : VGA_Synchro
	port map
	(
	clock_25Mhz		=> clk_25,
	red				=> r,
	green			=> g,
	blue			=> b,
	red_out			=> VGA_R(9),
	green_out		=> VGA_G(9),
	blue_out		=> VGA_B(9),
	horiz_sync_out	=> VGA_HS,
	vert_sync_out	=> VGA_VS,
	blank			=> VGA_BLANK,
	video_off		=> VIDEO_OFF,
	pixel_row		=> vga_y,
	pixel_column	=> vga_x	
	);
	
	Game_Logic : Game_Machine
	port map(
	clk				=> clk_25,
	clk_25			=> clk_25,
	reset			=> baba,
	start_P1		=> pad1_start,
	start_P2		=> '1',
	init			=> INIT,
	r				=> r,
	g				=> g,
	b				=> b,
	R_SRAM		=> r_ram,
	G_SRAM		=> g_ram,
	B_SRAM		=> b_ram,
	X_SRAM		=> ramX,
	Y_SRAM		=> ramY,
	SRAM_COMMAND => combinedComm,
	X_VGA			=> vga_x,
	Y_VGA			=> vga_y,
	init_x_P1		=> INIT_X_1,
	init_y_P1		=> INIT_Y_1,
	completed		=> oper_done,
	videoOff		=> VIDEO_OFF,
	P1_next_x		=> p1_n_x,
	P1_next_y		=> p1_n_y,
	out_pix			=> pixel_to_write
	);
	
	Snake1_controller :  Snake_Movement_Controller
	port map(
	trigger		=> VIDEO_OFF,
	init		=>	INIT,
	angle		=> P1_angle,
	next_x		=> p1_n_x,
	next_y		=> p1_n_y,
	init_x		=> INIT_X_1,
	init_y		=> INIT_Y_1

	);
end arch_top;